ACM/ICPC 之 简单DP-记忆化搜索与递推(POJ1088-滑雪)
递推型DP
将每个滑雪点都看作起点,从最低点开始逐个由四周递推出到达此点的最长路径的长度,由该点记下。
理论上,也可以将每一点都看作终点,由最高点开始计数,有兴趣可以试试。
//经典DP-由高向低海拔滑雪-求最长路 //Memory:372K Time:16 Ms #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define MAX 105 int row, col, len; int map[MAX][MAX]; //标准记录 int mov[4][2] = { { 1, 0 },{ -1, 0 },{ 0, 1 },{ 0, -1 } }; int d[MAX][MAX]; //dp[] int ans; /*各点属性*/ struct Node { int x, y; //坐标(x,y) int value; //海拔 }node[MAX*MAX]; bool operator < (const Node a, const Node b) { return a.value < b.value; } void DP() { ans = 0; memset(d, 0, sizeof(d)); for (int i = 0; i < len; i++) { int x = node[i].x, y = node[i].y; for (int j = 0; j < 4; j++) { int tx = x + mov[j][0]; int ty = y + mov[j][1]; if (tx >= 0 && tx < row && ty >= 0 && ty < col) { if (map[x][y] > map[tx][ty]) d[x][y] = max(d[x][y], d[tx][ty] + 1); } d[x][y] = max(1, d[x][y]); } ans = max(ans, d[x][y]); } return; } int main() { scanf("%d%d", &row, &col); len = 0; for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { scanf("%d", &map[i][j]); node[len].x = i; node[len].y = j; node[len++].value = map[i][j]; } } sort(node, node + len); //将各点按照-升序-排列 DP(); printf("%d\n", ans); return 0; }
记忆化搜索型DP
不必排序,解法和思路也相对更加清晰
1 //经典DP-由高向低海拔滑雪-求最长路 2 //Memory:252K Time:16 Ms 3 #include<iostream> 4 #include<cstring> 5 #include<cstdio> 6 using namespace std; 7 8 #define max(x,y) ((x)>(y)?(x):(y)) 9 #define MAX 105 10 11 int row, col; 12 int map[MAX][MAX]; //标准记录 13 int mov[4][2] = { { 1, 0 },{ -1, 0 },{ 0, 1 },{ 0, -1 } }; 14 int d[MAX][MAX]; //distance 15 int ans; 16 17 int DFS(int x, int y) 18 { 19 if (d[x][y]) return d[x][y]; 20 21 for (int i = 0; i < 4; i++) 22 { 23 int tx = x + mov[i][0]; 24 int ty = y + mov[i][1]; 25 if (tx >= 0 && tx < row && ty >= 0 && ty < col) 26 if (map[tx][ty] < map[x][y]) //向下滑雪 27 d[x][y] = max(DFS(tx, ty) + 1, d[x][y]); 28 } 29 30 ans = max(d[x][y], ans); 31 return d[x][y]; 32 } 33 34 int main() 35 { 36 scanf("%d%d", &row, &col); 37 38 for (int i = 0; i < row; i++) 39 for (int j = 0; j < col; j++) 40 scanf("%d", &map[i][j]); 41 42 memset(d, 0, sizeof(d)); 43 for (int i = 0; i < row; i++) 44 for (int j = 0; j < col;j++) 45 DFS(i,j); 46 47 printf("%d\n", ans + 1); 48 return 0; 49 }
他坐在湖边,望向天空,她坐在对岸,盯着湖面